<?php
class Verify_Code{
    protected $options =	array(
        'salt'     =>  '1234567890',
        'codeSet'   =>  '123456789abcdefhgijklmnopqrstuvwxyzABCDEFGHDIiJKLMNOPQRTUVWXY', 
        'expire'    =>  1800,        
        'fontSize'  =>  25,          
        'useCurve'  =>  true,        
        'useNoise'  =>  true,        
        'imageH'    =>  0,           
        'imageW'    =>  0,           
        'length'    =>  5,           
        'fontttf'   =>  '',          
        'bg'        =>  array(243, 251, 254),
        'reset'     =>  true,    
    );

    private $_image   = NULL; 
    private $_color   = NULL; 
    public function __construct($options = []){
        $this->options = array_merge($this->options, $options);
    }
    public function __get($name) {
        return $this->options[$name];
    }
    public function __set($name,$value){
        if(isset($this->options[$name])) {
            $this->options[$name] = $value;
        }
    }
    public function __isset($name){
        return isset($this->options[$name]);
    }
    public function check($code, $id = '') {
        // echo $code;
        $key = $this->md5Str($this->salt).$id;
        $session = Yaf_Session::getInstance();
        $session->start();
        $secode = $session->get($key);
        if(empty($secode)) {
            return false;
        }else{
            if(time() - $secode['verify_time'] > $this->expire) {
                $session->del($key);
                return false;
            }else{
                if($this->md5Str(strtoupper($code)) == $secode['verify_code']) {
                    $this->reset && $session->del($key);
                    return true;
                }else{
                    return false;
                }
            }
        }
    }

    public function execute($id = '') {
        $this->imageW || $this->imageW = $this->length*$this->fontSize*1.5 + $this->length*$this->fontSize/2; 
        $this->imageH || $this->imageH = $this->fontSize * 2.5;
        $this->_image = imagecreate($this->imageW, $this->imageH); 
        imagecolorallocate($this->_image, $this->bg[0], $this->bg[1], $this->bg[2]); 
        $this->_color = imagecolorallocate($this->_image, mt_rand(1,150), mt_rand(1,150), mt_rand(1,150));
        $ttfPath = dirname(__FILE__) . '/font'  . '/';
        if(empty($this->fontttf)){
            $dir = dir($ttfPath);
            $ttfs = array();		
            while (false !== ($file = $dir->read())) {
                if($file[0] != '.' && substr($file, -4) == '.ttf') {
                    $ttfs[] = $file;
                }
            }
            $dir->close();
            $this->fontttf = $ttfs[array_rand($ttfs)];
        } 
        $this->fontttf = $ttfPath . $this->fontttf;
        if ($this->useNoise) {
            $this->_writeNoise();
        } 
        $code = array();
        $codeNX = 0;

        for ($i = 0; $i<$this->length; $i++) {
            $code[$i] = $this->codeSet[mt_rand(0, strlen($this->codeSet)-1)];
            $codeNX  += mt_rand($this->fontSize*1.2, $this->fontSize*1.6);
            imagettftext(
                $this->_image,
                $this->fontSize,
                mt_rand(-40, 40),
                $codeNX, $this->fontSize*1.6,
                $this->_color, $this->fontttf,
                $code[$i]
            );
        }

        $key        =   $this->md5Str($this->salt);
        $code       =   $this->md5Str(strtoupper(implode('', $code)));
        $result     =   [];
        $result['verify_code'] = $code;
        $result['verify_time'] = time();
        $session = Yaf_Session::getInstance();
        $session->set($key.$id,$result);
        header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate');
        header('Cache-Control: post-check=0, pre-check=0', false);		
        header('Pragma: no-cache');
        header("Content-type: image/png");
        imagepng($this->_image);
        imagedestroy($this->_image);
    }
    private function _writeNoise() {
        $codeSet = '2345678abcdefhijkmnpqrstuvwxyz';
        for($i = 0; $i < 10; $i++){
            $noiseColor = imagecolorallocate($this->_image, mt_rand(150,225), mt_rand(150,225), mt_rand(150,225));
            for($j = 0; $j < 5; $j++) {
                imagestring($this->_image, 5, mt_rand(-10, $this->imageW),  mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);
            }
        }
    }
    private function md5Str($str){
        $key = substr(md5($this->salt), 5, 8);
        $str = substr(md5($str), 8, 10);
        return md5($key . $str);
    }

}
